package com.studentsystem.controller;

import cn.hutool.crypto.SecureUtil;
import com.studentsystem.common.Result;
import com.studentsystem.dataobject.UserDO;
import com.studentsystem.model.User;
import com.studentsystem.service.UserService;
import com.studentsystem.util.JwtUtils;
import com.studentsystem.util.MailUtils;
import com.studentsystem.util.UploadImgUtil;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.Objects;
import java.util.Random;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

/**
 * (User)表控制层
 */
@RestController
@RequestMapping("/user")
public class UserController {
    /**
     * 服务对象
     */
    @Resource
    private UserService userService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private JwtUtils jwtUtils;

    @Autowired
    private MailUtils mailUtils;

    @Autowired
    private UploadImgUtil uploadImgUtil;

    @PostMapping("/login")
    public Result<Object> login(@RequestBody User user, HttpServletResponse response) {
        if (user == null || StringUtils.isEmpty(user.getUsername())
                || StringUtils.isEmpty(user.getPassword())) {
            return Result.fail("登录user为空", null);
        }

        UserDO userDO = userService.queryByUsername(user.getUsername());
        if (userDO == null) {
            return Result.fail("该用户不存在", null);
        }
        System.out.println(user.getPassword());
        if (!userDO.getPwd().equals(SecureUtil.md5(user.getPassword()))) {
            return Result.fail("密码错误", null);
        }

        String jwtToken = jwtUtils.getJwtToken(user.getUsername());
        response.setHeader("Token", jwtToken);
        //暴露给外部的Header
        response.setHeader("Access-Control-Expose-Headers", "Token");

        user.setEmail(userDO.getEmail());
        user.setRole(userDO.getRole());
        user.setAvatar(userDO.getAvatar());
        return new Result<>(200, "登录成功", user);
    }

    @PostMapping("/register")
    public Result<Object> register(@RequestBody User user) {
        if (user == null || StringUtils.isEmpty(user.getUsername())) {
            return Result.fail("注册用户为空", null);
        }
        if (user.getCode() == null) {
            return Result.fail("验证码为空", null);
        }

        if (!user.getCode().equals(stringRedisTemplate.opsForValue().get(user.getEmail()))) {
            return Result.fail("验证码不正确或已过期", null);
        }

        UserDO userDO = new UserDO();
        userDO.setUsername(user.getUsername());
        userDO.setPwd(SecureUtil.md5(user.getPassword()));
        userDO.setEmail(user.getEmail());
        //默认注册学生
        userDO.setRole("student");
        userDO.setCreatedTime(LocalDateTime.now());
        userDO.setModifiedTime(LocalDateTime.now());

        UserDO insertUser = userService.insert(userDO);
        if (insertUser == null) {
            return Result.fail("注册失败", null);
        }
        return new Result<>(200, "注册成功", null);
    }

    @PostMapping("/forget")
    public Result<Object> forget(@RequestBody User user) {
        if (user == null || StringUtils.isEmpty(user.getUsername())) {
            return Result.fail("用户为空", null);
        }
        if (user.getCode() == null) {
            return Result.fail("验证码为空", null);
        }

        if (!user.getCode().equals(stringRedisTemplate.opsForValue().get(user.getEmail()))) {
            return Result.fail("验证码不正确或已过期", null);
        }

        UserDO userDO = userService.queryByUsername(user.getUsername());
        if (userDO == null) {
            return Result.fail("用户不存在", null);
        }

        userDO.setPwd(SecureUtil.md5(user.getPassword()));

        Boolean updateUser = userService.update(userDO);
        if (!updateUser) {
            return Result.fail("修改失败", null);
        }
        return new Result<>(200, "修改成功", user);
    }

    @GetMapping("/sendEmail")
    public Result<Object> sendEmail(@RequestParam("email") String email) {
        Random random = new Random();
        String code = String.valueOf(random.nextInt(9000) + 1000);
        //跳过发送的时间，先向客户端返回成功
        CompletableFuture.supplyAsync(() -> mailUtils.sendEmailCode(email, code));

        stringRedisTemplate.opsForValue().set(email, code, 5, TimeUnit.MINUTES);
        return Result.success(null);
    }

    @GetMapping("/logout")
    public Result<Object> logout() {
        SecurityUtils.getSubject().logout();
        return Result.success(null);
    }

    @GetMapping("/avatarSign")
    @RequiresAuthentication
    public Result<Map<String, String>> avatarSign(@RequestParam("role") String role,
                                                  @RequestParam("username") String username) {
        String dir = "avatar/" + role + "/" + username + "/";
        Map<String, String> sign = uploadImgUtil.getSign(dir);
        return Result.success(sign);
    }

    @GetMapping("/getUserInfo")
    public Result<UserDO> getUserInfo(@RequestParam("username") String username) {
        return Result.success(userService.queryByUsername(username));
    }

    @PutMapping("/updateUserInfo")
    public Result<String> updateUserInfo(@RequestBody User user) {
        if (user == null || user.getId() == null) {
            return Result.fail("用户为空", null);
        }

        UserDO userDO = new UserDO();
        userDO.setId(user.getId());
        userDO.setModifiedTime(LocalDateTime.now());
        if (StringUtils.isEmpty(user.getNewEmail())) {
            userDO.setAvatar(user.getAvatar());
        } else {
            if (Objects.equals(stringRedisTemplate.opsForValue().get(user.getEmail()), user.getCode())) {
                userDO.setEmail(user.getNewEmail());
            } else {
                return Result.fail("验证码错误", null);
            }
        }

        Boolean result = userService.update(userDO);
        if (result) {
            return Result.success("修改成功");
        } else {
            return Result.fail("修改失败", null);
        }

    }
}